#ifndef DataReader_H
#define DataReader_H

#include <string> // std::string, std::stoi 
#include <array>
#include <vector>
#include <map>

namespace Estimator
{
// This class is responsible for data reading from folder and files. The folder should contains txt files, each txt file contains
// a pose variable for current frame and observations. The name of each txt file can stands for the timestamp or ID for
// each frame.
class DataReader
{
  public:
    typedef std::array<double, 12 /*pose dimension*/> PoseType;
    typedef std::array<double, 2 /*observation dimension*/> ObservationType;
    typedef std::pair<size_t /*id for frame vertex*/, size_t /*id for landmark vertex*/> EdgeType;
    typedef std::map<EdgeType, ObservationType> ObservationsContainer;

    DataReader() = delete;
    virtual ~DataReader() = default;

    DataReader(std::string paramFolderName = "./Teng");
    // void YamlDataReader(std::string yamlFileName);

    // print all files for file names container...
    void printAll() const;
    void printPoses() const;
    void printObservations() const;
    void printFileNames() const;

    // Find the observation by frame id...
    std::pair<DataReader::ObservationsContainer::const_iterator, DataReader::ObservationsContainer::const_iterator>
    FindObservationRangeByFrameID(size_t idKey /*frame id*/) const;

    std::vector<PoseType> GetPoseContainer() const { return mvPoseVariables_; }
    ObservationsContainer GetObservatinsMap() const { return mMapObservationsAllFrames_; } 

    size_t getsizeofFrames() const {return mvPoseVariables_.size();}
  
  protected:
    // default extension set to be txt files...
    const std::string mExtension_ = ".txt";

    std::array<double, 9> mCalibration_; 

    // sort the file in increasing order according to their names..
    void sortFileNames();

    // read poses of each frame and their observations by scanning files..
    void readAllDataFromFiles();

    // file names container..
    std::vector<std::string> mvFileNames_;

    // pose variable container.. Pose container should be the same size with file names container, and the member
    // of pose container is the poses corresponding to the file names container.
    std::vector<PoseType> mvPoseVariables_;

    // Note map container is a sorted array in increasing order..
    // std::map<EdgeType, ObservationType>
    ObservationsContainer mMapObservationsAllFrames_;
};
}


#endif // DataReader_H